/**
 * $Id: IdGenerator.java 6 2011-09-14 00:18:07Z adriftrock@gmail.com $
 */

package com.swehr.server.daos.impl;

import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.swehr.utils.StringUtil;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Generate an identifier according to current records count.
 */
public class IdGenerator {
    private static Map<String, Integer> idMap =
            Collections.synchronizedMap(new HashMap<String, Integer>());

    private final static String MAX_PSN_ID = "?maxPsnId";

    private final static String MAX_ORG_ID = "?maxOrgId";

    private final static String MAX_POS_ID = "?maxPosId";

    private static IdGenerator idGen = null;

    private IdGenerator() throws Exception {
        if (idMap.isEmpty()) {
            initIdCache();
        }
    }

    private void initIdCache() throws Exception {
        StringBuffer cmd = new StringBuffer(1024);
        cmd.append("PREFIX ehr: ").append(Const.OWL_URL).append("\n");
        cmd.append("SELECT (MAX(?psnId) AS ").append(MAX_PSN_ID).append(")");
        cmd.append(" (MAX(?orgId) AS ").append(MAX_ORG_ID).append(")");
        cmd.append(" (MAX(?posId) AS ").append(MAX_POS_ID).append(")\n");
        cmd.append("WHERE {\n");
        cmd.append("  { GRAPH " + Const.GRAPH_PSN + " {?o ehr:hasId ?psnId} }\n");
        cmd.append("  UNION \n");
        cmd.append("  { GRAPH " + Const.GRAPH_ORG + " {?o ehr:hasId ?orgId} }\n");
        cmd.append("  UNION \n");
        cmd.append("  { GRAPH " + Const.GRAPH_POS + " {?o ehr:hasId ?posId} }\n");
        cmd.append("}");
        ConnectDao conn = new ConnectDao();
        ResultSet rs = conn.executeQuery(cmd.toString());
        while(rs.hasNext()) {
            QuerySolution qs = rs.nextSolution();

            RDFNode n = qs.get(MAX_POS_ID);
            String str = n == null ? "0" : qs.get(MAX_POS_ID).toString();
            Integer v = Integer.valueOf(StringUtil.trim(str));
            idMap.put(MAX_POS_ID, v);

            n = qs.get(MAX_PSN_ID);
            str = n == null ? "0" : qs.get(MAX_PSN_ID).toString();
            v = Integer.valueOf(StringUtil.trim(str));
            idMap.put(MAX_PSN_ID, v);

            n = qs.get(MAX_ORG_ID);
            str = n == null ? "0" : qs.get(MAX_ORG_ID).toString();
            v = Integer.valueOf(StringUtil.trim(str));
            idMap.put(MAX_ORG_ID, v);
        }
        conn.close();
    }

    /**
     * Update current maximum personnel identifier.
     * @param id int An identifier.
     */
    public void setMaxPsnId(int id) {
        idMap.put(MAX_PSN_ID, id);
    }

    /**
     * Get current maximum personnel identifier.
     * @return int An identifier.
     */
    public int getMaxPsnId() {
        return idMap.get(MAX_PSN_ID);
    }

    public void setMaxPosId(int id) {
        idMap.put(MAX_POS_ID, id);
    }

    public int getMaxPosId() {
        return idMap.get(MAX_POS_ID);
    }

    public void setMaxOrgId(int id) {
        idMap.put(MAX_ORG_ID, id);
    }

    public int getMaxOrgId() {
        return idMap.get(MAX_ORG_ID);
    }

    public static IdGenerator getInstance() throws Exception {
        if (idGen == null) {
            idGen = new IdGenerator();
        }
        return idGen;
    }

}
